﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Web;

namespace YoutubeDownloader
{
    public class Video
    {
        public string Id { get; set; }
        public DateTime Uploaded { get; set; }
        public DateTime Updated { get; set; }
        public string Uploader { get; set; }
        public string Title { get; set; }
        public string Category { get; set; }
        public string Description { get; set; }
        public int Duration { get; set; }
        public int Viewcount { get; set; }
        public object[] Tags;
        public string Thumbnail { get; set; }
        public Dictionary<string, object> Content;

        public string UrlToFlashPlayer 
        { 
            get
            {
                return "http://www.youtube.com/v/" + this.Id + "?hd=1&autoplay=1&allowfullscreen=true&showinfo=0&iv_load_policy=3&showsearch=0&fs=1";
            }
        }
        
        public List<VideoLink> Links;

        public Video()
        {
            
        }

        public Video(Dictionary<string, object> youtubeItemfromJson)
        {
            this.Id = (string)youtubeItemfromJson["id"];
            this.Uploaded = Video.JsonDateToDateTime((string)youtubeItemfromJson["uploaded"]);
            this.Updated = Video.JsonDateToDateTime((string)youtubeItemfromJson["updated"]);
            this.Uploader = (string)youtubeItemfromJson["uploader"];
            this.Title = (string)youtubeItemfromJson["title"];
            this.Category = (string)youtubeItemfromJson["category"];
            this.Description = (string)youtubeItemfromJson["description"];
            Dictionary<string, object> thumbnails = (Dictionary<string, object>)youtubeItemfromJson["thumbnail"];

            if (thumbnails.ContainsKey("hqDefault"))
            {
                this.Thumbnail = thumbnails["hqDefault"].ToString();
            }
            else
            {
                Thumbnail = string.Empty;
            }

            this.Content = (Dictionary<string, object>)youtubeItemfromJson["content"];
            this.Tags = (object[])youtubeItemfromJson["tags"];
            this.Duration = (int)youtubeItemfromJson["duration"];
            this.Viewcount = (int)youtubeItemfromJson["viewCount"];
        }

        public static DateTime JsonDateToDateTime(string jsonDate)
        {
            jsonDate = jsonDate.Replace("T", " ");
            jsonDate = jsonDate.Replace("Z", " ");
            DateTime dt;
            DateTime.TryParse(jsonDate, out dt);
            return dt;
        }

        public string FormattedLength()
        {
            string formattedLength;
            if (Duration < 60)
            {
                formattedLength = Duration + "s";
            }
            else if (Duration < 60 * 60)
            {
                formattedLength = Duration / 60 + "." + Duration % 60 + "s";
            }
            else
            {
                formattedLength = (Duration % 360) + ":" + (Duration % 360) / 60 + "." + Duration % 60 + "s";
            }
            return formattedLength;
        }

        public bool RefreshLinks()
        {
            bool rVal = true;

            string playContent = Finder.DownloadWebPage("http://youtube.com/get_video_info?video_id=" + this.Id);

            string[] array = playContent.Split(new string[] { "fmt_map=" }, 2, StringSplitOptions.RemoveEmptyEntries);

            Dictionary<string, string> formats = new Dictionary<string, string>();
            Dictionary<string, string> urls = new Dictionary<string, string>();

            if (array.Length > 1)
            {
                string fmtMap = array[1];

                array = fmtMap.Split(new string[] { "&" }, 2, StringSplitOptions.RemoveEmptyEntries);

                if (array.Length > 0)
                {
                    fmtMap = array[0];

                    fmtMap = HttpUtility.UrlDecode(fmtMap);

                    array = fmtMap.Split(new string[] { "," }, 32, StringSplitOptions.None);

                    foreach (string s in array)
                    {
                        string[] formatArray = s.Split(new string[] {"/"}, 32, StringSplitOptions.None);
                        formats[formatArray[0]] = formatArray[1];
                    }

                    Debug.WriteLine(fmtMap);
                }
            }

            array = playContent.Split(new string[] { "fmt_url_map=" }, 32, StringSplitOptions.RemoveEmptyEntries);

            if (array.Length > 1)
            {
                string urlMap = array[1];

                array = urlMap.Split(new string[] { "&" }, 32, StringSplitOptions.RemoveEmptyEntries);

                if (array.Length > 0)
                {
                    urlMap = array[0];

                    urlMap = HttpUtility.UrlDecode(urlMap);

                    array = urlMap.Split(new string[] { "," }, 32, StringSplitOptions.None);

                    foreach (string s in array)
                    {
                        string[] urlArray = s.Split(new string[] { "|" }, 32, StringSplitOptions.None);
                        urls[urlArray[0]] = urlArray[1];
                        Debug.WriteLine(s);
                    }

                    Debug.WriteLine(urlMap);
                }
            }

            Links = new List<VideoLink>();
            foreach (string key in urls.Keys)
            {
                Links.Add(new VideoLink(){Format = key, FormatDescription = formats[key], Link = urls[key], UpdateTick = System.Environment.TickCount});
            }

            return rVal;
        }

        public VideoLink FindBestVideoLink(string formatPreferred)
        {
            RefreshLinks();
            VideoLink url1080p = null; //37
            VideoLink url720p = null; //22
            VideoLink url480p = null; //35

            //37/1920x1080/9/0/115,22/1280x720/9/0/115,35/854x480/9/0/115

            foreach (VideoLink videoLink in Links)
            {
                switch (videoLink.Format)
                {
                    case "35":
                        url480p = videoLink;
                        break;
                    case "22":
                        url720p = videoLink;
                        break;
                    case "37":
                        url1080p = videoLink;
                        break;
                }
            }

            if( formatPreferred == "480p")
            {
                return url480p;
            }
            
            if(formatPreferred == "720p")
            {
                return url720p ?? url480p;
            }
            
            if(formatPreferred == "1080p")
            {
                return url1080p ?? (url720p ?? url480p);
            }

            return null;
        }
    }



    public class VideoLink
    {
        public int UpdateTick;
        public string Format;
        public string FormatDescription;
        public string Link;
    }
}
